package ru.spbau.bytecode.graph;

//import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.awt.Dimension;
import java.awt.Point;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.Set;

import org.junit.Before;
import org.junit.Test;

import ru.spbau.bytecode.graph.CompositeVertex;
import ru.spbau.bytecode.graph.Edge;
import ru.spbau.bytecode.graph.Graph;
import ru.spbau.bytecode.graph.Vertex;

public class GraphTest {
	
	private final List<CompositeVertex> compositeVertices =
		new LinkedList<CompositeVertex>();
	private final List<Vertex> simpleVertices = new LinkedList<Vertex>();
	private final Set<Edge> edges = new HashSet<Edge>();
	private final static int SIMPLE_VERTICES_NUMBER = 10;
	private final static int COMPOSITE_VERTICES_NUMBER = 10;
	private final Graph graph = new Graph();
	
	@Before
	public void setUp() {
		for (int i = 0; i < COMPOSITE_VERTICES_NUMBER; i++) {
			CompositeVertex v = new CompositeVertex("v" + Integer.toString(i));
			compositeVertices.add(v);
			
			for (int j = 0; j < SIMPLE_VERTICES_NUMBER; j++) {
				Vertex u = new Vertex(Integer.toBinaryString(j));
				simpleVertices.add(u);
				v.addInnerVertex(u);
			}
			
			graph.addVertex(v);
		}
		
		Random rand = new Random(666);
		for (Vertex v1: simpleVertices) {
			for (Vertex v2: simpleVertices) {
				int p = rand.nextInt() % 2;
				if (p == 1) {
					edges.add(new Edge(v1, v2));
				}
			}
		}
	}

	@Test
	public void testAddVertex() {
		assertEquals(compositeVertices, graph.getVertices());
	}
	
	@Test
	public void testAddEdge() {
		for (Edge e: edges) {
			graph.addEdge(e);
		}
		
		assertEquals(edges, graph.getEdges());
	}
	
	@Test(expected = IllegalStateException.class)
	public void testIllegalStateException() {
		Vertex v = new Vertex("not existing vertex 1");
		Vertex u = new Vertex("not existing vertex 2");
		graph.addEdge(new Edge(v, u));
	}
	
	@Test
	public void testCatchVertexAtPoint() {
		CompositeVertex catchedCompositeVertex = null;
		Vertex catchedSimpleVertex = null;
		
		for (CompositeVertex v: compositeVertices) {
			v.setSize(new Dimension(3, 3));
			v.setLocation(new Point(0, 0));
			catchedCompositeVertex = v;
			
			for (Vertex u: v.getInnerVertices()) {
				u.setSize(new Dimension(1, 1));
				u.setLocation(new Point(0, 0));
				catchedSimpleVertex = u;
			}
		}
		
		graph.catchVertexAtPoint(new Point(1, 1));
		assertTrue(catchedSimpleVertex.isCatched());
		for (CompositeVertex v: compositeVertices) {
			assertFalse(v.isCatched());
			for (Vertex u: v.getInnerVertices()) {
				if (!u.equals(catchedSimpleVertex)) {
					assertFalse(u.isCatched());
				}
			}
		}
		
		graph.catchVertexAtPoint(new Point(2, 2));
		assertTrue(catchedCompositeVertex.isCatched());
		for (Vertex u: catchedCompositeVertex.getInnerVertices()) {
			assertTrue(u.isCatched());
		}
	}
	
	@Test
	public void testFreeCatchedVertices() {
		CompositeVertex v = compositeVertices.get(0);
		v.setCatched(true);
		
		graph.freeCatchedVertices();
		assertFalse(v.isCatched());
		for (Vertex u: v.getInnerVertices()) {
			assertFalse(u.isCatched());
		}
	}
	
	@Test
	public void testCalculateGraphSize() {
		for (CompositeVertex v: compositeVertices) {
			v.setSize(new Dimension(5, 7));
			v.setLocation(new Point(7, 1000));
		}
		
		Dimension graphSize = graph.calculateGraphSize();
		assertEquals(12, graphSize.width);
		assertEquals(1007, graphSize.height);
	}
}
